﻿using System;
using System.Collections.Generic;
using System.Text;
using agsXMPP;
using agsXMPP.protocol.client;
using agsXMPP.protocol.x.muc;
using System.Security;

namespace PoshXmpp
{
    public class XmppClient : XmppClientConnection
    {
        public MessageManager MessageManager { get; set; }
        public ContactManager ContactManager { get; set; }
        public GroupChatManager ChatManager { get; set; }
        public ReconnectManager ReconnectManager { get; set; }
        
        
        /// <summary>
        /// A circular reference to myself, just so I can pass ValueFromPipelineByPropertyName
        /// </summary>
        public XmppClient Client { get { return this; } }

        Jid _me;
        SecureString _password;

        new public SecureString Password { 
            get { return _password; }
            set { 
                _password = value; 
                IntPtr BSTR = System.Runtime.InteropServices.Marshal.SecureStringToBSTR(_password);
                base.Password = System.Runtime.InteropServices.Marshal.PtrToStringAuto(BSTR);
                System.Runtime.InteropServices.Marshal.ZeroFreeBSTR(BSTR);
            }
        }

        [Obsolete("Use SecureString Passwords via the Password property")]
        public void SetPassword(string password)
        {
            base.Password = password;
            _password = new SecureString();
            foreach (char c in password)
            {
                _password.AppendChar(c);
            }
        }

        #region constructors
        public XmppClient(string jabberId, SecureString password) : this(new Jid(jabberId), password, false) { }
        public XmppClient(Jid user, SecureString password) : this(user, password, user.Server, false) { }

        public XmppClient(string jabberId, SecureString password, bool reconnect) : this(new Jid(jabberId), password, reconnect) { }
        public XmppClient(Jid user, SecureString password, bool reconnect) : this(user, password, user.Server, reconnect) { }

        public XmppClient(string jabberId, SecureString password, string server) : this(new Jid(jabberId), password, server, false) { }
        public XmppClient(Jid user, SecureString password, string server) : this(user, password, server, false) { }

        public XmppClient(string jabberId, SecureString password, string server, bool reconnect) : this(new Jid(jabberId), password, server, reconnect) { }
        public XmppClient(Jid user, SecureString password, string server, bool reconnect)
            : base(server)
        {
            _me = user;
            MessageManager = new MessageManager(this);
            ContactManager = new ContactManager(this);
            ChatManager = new GroupChatManager(this);
            if (reconnect)
            {
                ReconnectManager = new ReconnectManager(this);
            }

            //AutoAgents = true;
            //AutoRoster = true;

            base.Username = _me.User;
            Password = password;
        }
        #endregion

        public IEnumerable<Message> Messages
        {
            get
            {
                return MessageManager.Messages;
            }
        }

        public bool HasMessages
        {
            get
            {
                return MessageManager.HasMessages;
            }
        }

        public IEnumerable<Jid> OnlineContacts
        {
            get
            {
                return ContactManager.OnlineContacts;
            }
        }

        public IEnumerable<Jid> ContactRequests
        {
            get
            {
                foreach( Presence p in  ContactManager.ContactRequests ) 
                { 
                    yield return p.From; 
                }
            }
        }

        public void AddBuddy(Jid From)
        {
            ContactManager.AddContact(From);
        }

        public void RemoveBuddy(Jid From)
        {
            ContactManager.RemoveContact(From);
        }

        public void JoinChat(Jid room)
        {
            ChatManager.JoinRoom(room, this.Username);
        }

        public void JoinChat(Jid room, string Nick)
        {
            ChatManager.JoinRoom(room, Nick);
        }

        public void JoinChat(Jid room, string Nick, string Password)
        {
            ChatManager.JoinRoom(room, Nick, Password);
        }

        public void LeaveChat(Jid room)
        {
            ChatManager.LeaveRoom(room);
        }


        public void SendMsg(Jid to, String message)
        {
            if (ChatManager.IsInRoom(to))
                base.Send(new Message(to, MessageType.groupchat, message));
            else
                base.Send(new Message(to, MessageType.chat, message));
        }

        public void SendMsg(String to, String message)
        {
            if (ChatManager.IsInRoom(to))
                base.Send(new Message(to, MessageType.groupchat, message));
            else
               base.Send(new Message(to, MessageType.chat, message));
        }

        public void SendMsg(String to, String message, MessageType type)
        {
           base.Send(new Message(to, type, message));
        }

        public void SendMsg(Jid to, String message, MessageType type)
        {
           base.Send(new Message(to, type, message));
        }

        public override void Close()
        {
            ChatManager.Close();
            if (ReconnectManager != null) { ReconnectManager.Close(); }
            base.Close();
        }
    }
}
